package main

import (
	"log"
	"math/rand"
	"net"
	"strconv"
	"time"

	"gitee.com/zhaoqinghuan/rpc"
	"gitee.com/zhaoqinghuan/rpc/serialization"
)

type EchoServer struct {
	conn       *net.UDPConn
	serializer serialization.Serializer
}

func NewEchoServer(port int, serializer serialization.Serializer) *EchoServer {
	addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:"+strconv.Itoa(port))

	if err != nil {
		log.Println(err)
		return nil
	}
	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		log.Println(err)
		return nil
	}

	return &EchoServer{
		conn:       conn,
		serializer: serializer,
	}
}

func (server EchoServer) Serve() {
	defer server.conn.Close()
	for {
		request := make([]byte, 4096)
		n, remoteAddr, err := server.conn.ReadFromUDP(request)
		if err != nil {
			log.Println(err)
			return
		}

		go server.Handle(request[:n], remoteAddr)
	}
}

func (server EchoServer) Handle(request []byte, remoteAddr *net.UDPAddr) {
	var data rpc.RpcData
	err := server.serializer.Unmarshal(request, &data)
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("receive request %+v from %s\n", data, remoteAddr.String())
	time.Sleep(time.Millisecond * time.Duration(rand.Intn(500)))
	stream, err := server.serializer.Marshal(data)
	if err != nil {
		log.Println(err)
		return
	}
	_, err = server.conn.WriteToUDP(stream, remoteAddr)
	if err != nil {
		log.Println(err)
		return
	}
	log.Printf("send response  to %s\n", remoteAddr.String())
}

func main() {
	server := NewEchoServer(5678, rpc.Serializer)
	server.Serve()
}
